
/**
 * 事件管理系统核心模块
 */
export class EventManager {
    private static _instance: EventManager;
    private _eventMap: Map<string, Array<{ callback: Function, target: any, once?: boolean }>> = new Map();

    public static getInstance(): EventManager {
        if (!this._instance) {
            this._instance = new EventManager();
        }
        return this._instance;
    }

    // 监听事件
    public on(eventName: string, callback: Function, target?: any): void {
        if (!this._eventMap.has(eventName)) {
            this._eventMap.set(eventName, []);
        }
        this._eventMap.get(eventName)?.push({ callback, target });
    }

    // 一次性监听
    public once(eventName: string, callback: Function, target?: any): void {
        if (!this._eventMap.has(eventName)) {
            this._eventMap.set(eventName, []);
        }
        this._eventMap.get(eventName)?.push({ callback, target, once: true });
    }

    // 触发事件
    public emit(eventName: string, ...args: any[]): void {
        const listeners = this._eventMap.get(eventName);
        if (!listeners || listeners.length === 0) return;

        // 遍历执行并过滤一次性监听
        const keepListeners = [];
        for (const listener of listeners) {
            listener.callback.apply(listener.target, args);
            if (!listener.once) {
                keepListeners.push(listener);
            }
        }
        this._eventMap.set(eventName, keepListeners);
    }

    // 移除监听
    public off(eventName: string, callback?: Function, target?: any): void {
        if (!this._eventMap.has(eventName)) return;

        if (!callback) {
            // 移除该事件所有监听
            this._eventMap.delete(eventName);
        } else {
            // 移除特定监听
            const listeners = this._eventMap.get(eventName)!;
            const newListeners = listeners.filter(listener =>
                !(listener.callback === callback && (!target || listener.target === target))
            );
            if (newListeners.length === 0) {
                this._eventMap.delete(eventName);
            } else {
                this._eventMap.set(eventName, newListeners);
            }
        }
    }

    // 移除所有与指定target相关的事件监听
    public offAllByTarget(target: any): void {
        if (!target) return;
        for (const [eventName, listeners] of this._eventMap) {
            const newListeners = listeners.filter(listener => listener.target !== target);
            if (newListeners.length === 0) {
                this._eventMap.delete(eventName);
            } else {
                this._eventMap.set(eventName, newListeners);
            }
        }
    }

    // 清空所有事件
    public clear(): void {
        this._eventMap.clear();
    }
}


/**
 * 定义一个装饰器，用于自动移除事件
 */
import { Node } from 'cc';
export function AutoOff(eventManager: EventManager) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;
        descriptor.value = function (this: any, ...args: any[]) {
            // 在组件挂载时，将事件管理器与组件绑定，并在组件销毁时自动移除
            if (this.node) {
                // 假设组件有node属性（cc.Component）
                this.node.on(Node.EventType.NODE_DESTROYED, () => {
                    eventManager.offAllByTarget(this);
                });
            }
            return originalMethod.apply(this, args);
        };
    };
}
